﻿using dz.loger.core;
using dz.util.core;
using Dz.WorkerService.jkyschema;
using Dz.WorkerService.QueryParm;
using Dz.WorkerService.Service;
using Microsoft.Identity.Client;
using System.Data;

namespace Dz.WorkerService
{
    public class TaskSo : BaseTaskItem
    {
        int cnt = 0;
        public TaskSo(string name, TimeSpan interval) : base(name, interval)
        {
            docType = "so";
            method = "oms.trade.fullinfoget";
            table = "dz_jky_SO";
        }

        protected override async Task SyncToU9()
        {
            OfflineSipService offlineSip = new OfflineSipService(processId);
            TransferinService transferin = new TransferinService(processId);

            await offlineSip.ImportData();
            await transferin.ImportData();
        }
        protected override BaseParm BuildParm(DateTime sdate, DateTime edate)
        {
            TransferInParm parm = new TransferInParm();

            parm.startConsignTime = sdate.ToString("yyyy-MM-dd HH:mm:ss");
            parm.endConsignTime = edate.ToString("yyyy-MM-dd HH:mm:ss");
            parm.fields = @"tradeNo,chargeCurrency,goodsDetail.goodsNo,goodsDetail.sellCount,goodsDetail.unit,goodsDetail.platCode,goodsDetail.platGoodsId,
                            customerCode,warehouseCode,warehouseName,tradeId,shopcode,scrollId,goodsDetail.isFit,flagNames,goodsDetail.sellTotal,goodsDetail.taxFee,
                            tradeOrderAssemblyGoodsDtoList.sellTotal,tradeOrderAssemblyGoodsDtoList.taxFee,tradeOrderAssemblyGoodsDtoList.goodsNo,consignTime,
                            tradeOrderAssemblyGoodsDtoList.taxRate,tradeOrderAssemblyGoodsDtoList.sellCount,tradeOrderAssemblyGoodsDtoList.sellTotal,flagNames,
                            goodsDetail.subTradeId,tradeOrderAssemblyGoodsDtoList.subTradeId,isBillCheck,billDate,isDelete,tradeStatus,payment,finReceiptTime,
                            goodsDetail.shareFavourableFee,tradeOrderAssemblyGoodsDtoList.unit";

            return parm;
        }
        /// <summary>
        /// 将销售参数转换成线上订单的参数
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        private BaseParm ConvertParm(BaseParm parm)
        {
            TransferInParm parm1 = (TransferInParm)parm;

            parm1.startBillDate = parm1.startConsignTime;
            parm1.endBillDate = parm1.endConsignTime;

            parm1.startConsignTime = "";
            parm1.endConsignTime = "";
            parm1.scrollId = "";
            
            return parm1;
        }

        /// <summary>
        /// 获得数据表
        /// </summary>
        /// <returns></returns>
        public DataTable GetTable()
        {
            DataTable table = new DataTable();


            table.Columns.Add("shopcode", typeof(string));
            table.Columns.Add("deptcode", typeof(string));
            table.Columns.Add("org", typeof(string));
            table.Columns.Add("wh", typeof(string));
            table.Columns.Add("tradeno", typeof(string));
            table.Columns.Add("tradeid", typeof(string));
            table.Columns.Add("parent", typeof(string));
            table.Columns.Add("goodsno", typeof(string));
            table.Columns.Add("sellcount", typeof(decimal));
            table.Columns.Add("sellamt", typeof(decimal));
            table.Columns.Add("orgamt", typeof(decimal));
            table.Columns.Add("platcode", typeof(string));            
            table.Columns.Add("shipdate", typeof(DateTime));
            table.Columns.Add("isfit", typeof(int));
            table.Columns.Add("flag", typeof(int));
            table.Columns.Add("cust",typeof(string));
            table.Columns.Add("price", typeof(decimal));
            table.Columns.Add("payment",typeof(decimal));
            table.Columns.Add("discount", typeof(decimal));
            

            return table;
        }
        private record Item(string Id, string Code, decimal Amt,decimal discount);

        /// <summary>
        /// 新增数据
        /// </summary>
        /// <param name="dt">数据表</param>
        /// <param name="item">吉客云数据</param>
        /// <param name="xtype"> 1：线下订单，调拨订单 2：线上订单</param>
        private void AddData(DataTable dt, TradeItem item,int xtype)
        {
            try
            {
                string a = item.tradeNo;
                List<Item> items = new List<Item>();

                int flag = (xtype == 1) ? 1 : 2;

                decimal payment = item.payment;
                decimal total = 0;
                string firstParent = string.Empty;

                string flagNames = item.flagNames ?? string.Empty;

                if (item.isDelete == 1 || flagNames.Contains("无效订单") || string.IsNullOrEmpty(item.warehouseCode)
                    || item.tradeStatus == "5010" || flagNames.Contains("补录单")) return;
                //if (item.flagNames.Contains("补录单")) return;

                //如果是有对账日期，但对账状态不是已对账的，不处理
                //处理生成线上出货数据
            
                if (xtype == 2 && (item.isBillCheck != 1 || flagNames.Contains("线下订单"))) return;
              


                if (flagNames.Contains("线下订单"))
                {
                    flag = 3;
                }
                if (item.goodsDetail == null || item.goodsDetail.Count == 0) return;

                List<DataRow> rows = new List<DataRow>();

                foreach (var row in item.goodsDetail)
                {
                    //组合件需要从组装明细获取
                    if (row.isFit == 1)
                    {
                        items.Add(new Item(row.subTradeId,row.goodsNo,row.sellTotal,row.shareFavourableFee));         
                        if(firstParent.Length == 0) firstParent = row.goodsNo;
                        continue;
                    }

                    DataRow dr = dt.NewRow();

                    dr["payment"] = item.payment;
                    dr["shopcode"] = item.shopCode;
                    dr["deptcode"] = item.shopCode.Split("-")[0];
                    dr["org"] = item.shopCode.Split("-")[1];
                    dr["wh"] = item.warehouseCode;
                    dr["tradeno"] = item.tradeNo;
                    dr["tradeid"] = item.tradeId;
                    dr["goodsno"] = row.goodsNo;
                    dr["sellcount"] = row.sellCount;
                    dr["platcode"] = row.platCode;
                    dr["flag"] = flag;
                    //dr["sellamt"] = row.sellTotal;
                    dr["orgamt"] = row.sellTotal;
                    dr["discount"] = row.shareFavourableFee;
                    dr["sellamt"] = row.sellTotal - row.shareFavourableFee;
                    total = total + row.sellTotal;
                    dr["isfit"] = 0;
                    dr["price"] = row.sellCount == 0 ? Math.Abs(row.sellTotal) : Math.Round(row.sellTotal / row.sellCount, 6);

                    dr["shipdate"] = (xtype == 1) ? item.consignTime.Date : item.finReceiptTime.Date;
                    dr["cust"] = item.customerCode;

                    rows.Add(dr);
                }

                ProcessFit(ref rows, item, dt, items, flag, ref total,xtype);

                #region 调整金额
                //if (payment != total)
                //{
                //    decimal dif = payment - total;

                //    if (firstParent.Length == 0)
                //    {
                //        decimal amt = Convert.ToDecimal(rows[0]["sellamt"]) + dif;
                //        rows[0]["sellamt"] = amt;
                //        rows[0]["orgamt"] = amt;
                //        decimal sellCount = Convert.ToDecimal(rows[0]["sellcount"]);
                //        rows[0]["price"] = sellCount == 0 ? Math.Abs(amt) : Math.Round(amt / sellCount, 6);
                //    }
                //    else
                //    {
                //        foreach (DataRow dr in rows) 
                //        {
                //            if (dr["parent"].ToString() != firstParent) continue;

                //            decimal amt = Convert.ToDecimal(dr["sellamt"]) + dif;
                //            dr["sellamt"] = amt;
                //            dr["orgamt"] = amt;
                //        }
                //    }
                //}
                #endregion

                foreach (var row in rows) 
                {
                    dt.Rows.Add(row);
                }
            }
            catch (Exception ex)
            {
                LogUtil.Instance.Error(ex);
                LogUtil.Instance.Error(ex.StackTrace);
                throw;
            }
            
        }

        private BaseParm RebuildParm(BaseParm parm, string scrollId)
        {
            TransferInParm rtn = parm as TransferInParm;

            rtn.scrollId = scrollId;

            return rtn;
        }

        public async Task aaa(DateTime sdate, DateTime edate)
        {
            string scrollId = Guid.NewGuid().ToString();
            processId = scrollId;

            DataTable data = GetTable();

            try
            {
               BaseParm parm = BuildParm(sdate, edate);
               parm = parm = ConvertParm(parm);  

                await AddData(processId, parm, data, 2);

                data.DefaultView.Sort = "shipdate";

                DataTable tmp = data.DefaultView.ToTable();
                tmp.TableName = "TEST";
                tmp.WriteXml(@"c:\2.xml", XmlWriteMode.WriteSchema);

                await sqlUtils.Save(data, "dz_jky_SO");

                //await UpdateSyncLog(processId, 1);
                await UpdateDataState(1);
                await AdjustAmt();
                //await SetLastDate();
            }
            catch (Exception ex)
            {
                await UpdateSyncLog(processId, -1, ex.Message);
                LogUtil.Instance.Error($"同步{docType}失败：{ex.Message}");
                throw new Exception(ex.Message);
            }
        }
        protected override async Task DownLoadData(BaseParm parm)
        {
            await base.DownLoadData(parm);

            string scrollId = Guid.NewGuid().ToString();
            processId = scrollId;

            DataTable data = GetTable();

            try
            {
                await InsertSyncLog(processId, docType);

                await AddData(scrollId, parm, data,1);

                parm = ConvertParm(parm);

                await AddData(processId, parm, data,2);

                data.DefaultView.Sort = "shipdate";

                DataTable tmp = data.DefaultView.ToTable();
                tmp.TableName = "TEST";
                tmp.WriteXml(@"c:\2.xml", XmlWriteMode.WriteSchema);

                await sqlUtils.Save(data, "dz_jky_SO");
                
                await UpdateSyncLog(processId, 1);
                await UpdateDataState(1);
                await AdjustAmt();
                await SetLastDate();
            }
            catch (Exception ex)
            {
                await UpdateSyncLog(processId, -1, ex.Message);
                LogUtil.Instance.Error($"同步{docType}失败：{ex.Message}");
                throw new Exception(ex.Message);
            }
        }

        private void ProcessFit(ref List<DataRow> rows,TradeItem item,DataTable dt, List<Item> items,int flag,ref decimal total,int xtype)
        {
            if (item.tradeOrderAssemblyGoodsDtoList == null || item.tradeOrderAssemblyGoodsDtoList.Count == 0) return;

            string parent = string.Empty;
            ///处理组装件
            foreach (var row in item.tradeOrderAssemblyGoodsDtoList)
            {

                DataRow dr = dt.NewRow();


                dr["payment"] = item.payment;
                dr["shopcode"] = item.shopCode;
                dr["deptcode"] = item.shopCode.Split("-")[0];
                dr["org"] = item.shopCode.Split("-")[1];
                dr["wh"] = item.warehouseCode;
                dr["tradeno"] = item.tradeNo;
                dr["tradeid"] = item.tradeId;
                dr["goodsno"] = row.goodsNo;
                dr["shipdate"] = (xtype == 1) ? item.consignTime.Date : item.finReceiptTime.Date;
                dr["sellcount"] = row.sellCount;
                dr["isfit"] = 1;
                Item find = items.FirstOrDefault(x => x.Id == row.subTradeId);
                dr["parent"] = find.Code;
                //dr["sellamt"] = find.Amt;
                dr["discount"] = find.discount;
                dr["orgamt"] = find.Amt;
                dr["sellamt"] = find.Amt-find.discount;
                dr["flag"] = flag;
                dr["price"] = 0;
                dr["cust"] = item.customerCode;

                if (parent != find.Code)
                {
                    parent = find.Code;
                    total += find.Amt;
                }
                rows.Add(dr);

            }
        }

        private async Task AddData(string scrollId,BaseParm parm,DataTable data,int type)
        {
            int cnt = 0;
            while (!string.IsNullOrEmpty(scrollId))
            {
                if (type == 1)
                {
                    LogUtil.Instance.Debug($"按发货时间下载数据：{scrollId}，次数{++cnt}");
                }
                else
                {
                    LogUtil.Instance.Debug($"按对账时间下载数据：{scrollId}，次数{++cnt}");
                }

                    WebResult result = await JkyUtils.PostByQM(method, JsonUtil.Serialize(parm));

                #region 判断http请求是否成功
                if (!result.Sucess)
                    if (!result.Sucess)
                    {
                        throw new Exception($"下载{docType}失败：{result.Data}");
                    }
                #endregion

                #region 判断请求结构是否成功
                QmResult result1 = JsonUtil.Deserialize<QmResult>(result.Data);
                if (result1.jackyunCode != "200")
                {
                    throw new Exception($"下载{docType}失败：{result1.jackyunMessage}");
                }
                #endregion

                #region 处理请求结果
                
                scrollId = result1.scrollId;

                parm = RebuildParm(parm, scrollId);

                if (result1.trades == null || result1.trades.Count == 0) continue;
                foreach (TradeItem item in result1.trades)
                {
                    //string no = item.tradeNo;
                    //if (no == "JY202508070234")
                    //{ 
                    //    int a = 1;
                    //}
                    AddData(data, item, type);
                }
                #endregion

            }
        }
        private async Task AdjustAmt()
        {
            string sql = $"exec usp_dz_jky_adjustsoamt";

            await sqlUtils.ExecuteNonQuery(sql);
        }
    }
}
